import requests
import re
from common.read_excel import ReadExcel
from common.role_factory import RoleFactory
from common.read_sql import read_sql


class RequestMethod:
    def __init__(self):
        self.read = ReadExcel()
        # 实例化一个session对象
        self.session = requests.session()
        # 获取各个身份的token
        self.school1001token = RoleFactory().creat_role("school1001")
        self.school1002token = RoleFactory().creat_role("school1002")
        self.county1003token = RoleFactory().creat_role("county1003")
        self.county1004token = RoleFactory().creat_role("county1004")
        self.city1005token = RoleFactory().creat_role("city1005")
        self.roottoken = RoleFactory().creat_role("root")

    # 封装各种请求方法
    def send_request(self, method, url, params=None, header=None):
        # 封装get请求方法
        if method == "GET":
            if header != None and "Content-Type" in header.keys():
                if header["Content-Type"] == "application/json":
                    return self.session.get(url, json=params, headers=header, verify=False)
                elif header["Content-Type"] == "application/x-www-form-urlencoded":
                    return self.session.get(url, data=params, headers=header, verify=False)
            else:
                return self.session.get(url, params=params, headers=header, verify=False)
        # 封装post请求方法
        if method == "POST":
            if header != None and "Content-Type" in header.keys():
                if header["Content-Type"] == "application/json":
                    return self.session.post(url, json=params, headers=header, verify=False)
                elif header["Content-Type"] == "application/x-www-form-urlencoded":
                    return self.session.post(url, data=params, headers=header, verify=False)
            else:
                return self.session.post(url, data=params, headers=header, verify=False)
        # 封装delete请求方法
        if method == "DELETE":
            if header != None and "Content-Type" in header.keys():
                if header["Content-Type"] == "application/json":
                    return self.session.delete(url, json=params, headers=header, verify=False)
                elif header["Content-Type"] == "application/x-www-form-urlencoded":
                    return self.session.delete(url, data=params, headers=header, verify=False)
            else:
                return self.session.delete(url, data=params, headers=header, verify=False)
        # 封装put请求方法
        if method == "PUT":
            if header != None and "Content-Type" in header.keys():
                if header["Content-Type"] == "application/json":
                    return self.session.put(url, json=params, headers=header, verify=False)
                elif header["Content-Type"] == "application/x-www-form-urlencoded":
                    return self.session.put(url, data=params, headers=header, verify=False)
            else:
                return self.session.put(url, data=params, headers=header, verify=False)

    # 往请求头更新身份token
    def get_updatetoken_case_header(self, row):
        if self.read.get_case_identity(row) != None:
            header = self.read.get_case_headers_value(row)
            if self.read.get_case_identity(row) == "school_1001":
                header["Authorization"] = self.school1001token
            elif self.read.get_case_identity(row) == "school_1002":
                header["Authorization"] = self.school1002token
            elif self.read.get_case_identity(row) == "county_1003":
                header["Authorization"] = self.county1003token
            elif self.read.get_case_identity(row) == "county_1004":
                header["Authorization"] = self.county1004token
            elif self.read.get_case_identity(row) == "city_1005":
                header["Authorization"] = self.city1005token
            elif self.read.get_case_identity(row) == "root":
                header["Authorization"] = self.roottoken
            return header
        else:
            return self.read.get_case_headers_value(row)

    # 往请求头里面添加Content-Type
    def get_updatacontenttype_case_header(self, row):
        header = self.get_updatetoken_case_header(row)
        if self.read.get_case_paramstype(row) != None and header != None:
            if self.read.get_case_paramstype(row) == "JSON":
                header["Content-Type"] = "application/json"
            elif self.read.get_case_paramstype(row) == "DATA":
                header["Content-Type"] = "application/x-www-form-urlencoded"
            elif self.read.get_case_paramstype(row) == "PARAMS":
                header = header
            return header
        else:
            return header

    # 更新URL
    def get_updata_case_URL(self, row):
        # 得到原来的url
        old_URL = self.read.get_case_url(row)
        # 判断URL是否包含"{id}",且前置sql不为空
        if "{id}" in old_URL and self.read.get_case_beforesql_key(row) != None:
            id = str(read_sql(self.read.get_case_beforesql_value(row)))
            new_url = old_URL.replace("{id}", id)
            return new_url
        else:
            return old_URL

    # 请求接口,获取响应结果
    def get_actual_result(self, method, url, params=None, header=None):
        responseObject = self.send_request(method, url, params, header)
        return responseObject

    # ----------------------------------------处理前置用例----------------------------------------------------
    """
    执行数据关联用例的思路:1.先获取前置用例的行号 2.根据行号获取method,url,params,执行前置用例 3.根据正则表达式从前置用例的响应中提取value组成键值对 
    4.提取到的value值和依赖字段key组成键值对,更新到请求参数中;5执行用例,获取实际结果
    """

    # 获取前置用例行号
    def get_beforecaseid_case_row(self, row):
        beforecaseid = self.read.get_case_beforecaseid(row)
        for i in range(2, self.read.get_row_count() + 1):
            case_id = self.read.get_case_id(i)
            if case_id == beforecaseid:
                return i

    # 执行前置用例,提取响应,返回键值对
    def get_denpendent_key_value(self, row):
        # 获取前置用例的行号
        beforecaseid_case_row = self.get_beforecaseid_case_row(row)
        # 获取前置用例的方法,URL,参数,请求头
        method = self.read.get_case_method(beforecaseid_case_row)
        url = self.get_updata_case_URL(beforecaseid_case_row)
        params = self.read.get_case_params_value(beforecaseid_case_row)
        header = self.get_updatacontenttype_case_header(beforecaseid_case_row)
        # 执行前置用例,获取响应结果
        beforecaseid_case_actual = self.get_actual_result(method, url, params, header)
        try:
            # 将响应结果转换为json格式
            actual = beforecaseid_case_actual.json()
        except:
            # 将响应结果转换为text格式
            actual = beforecaseid_case_actual.text
        # 判断响应结果数据类型:如果响应是字典类型且正则表达式为空
        if isinstance(actual, dict) and self.read.get_case_regular(
                beforecaseid_case_row) == None:
            key = self.read.get_case_dependent(beforecaseid_case_row)
            # 判断依赖字段是否为用逗号隔开的多个字段
            if "," in key:  # 如果是多个字段
                list1 = []
                dict1 = {}
                list1 = key.split(",")
                for i in list1:
                    dict1[i] = actual[i]
                return dict1
            else:  # 如果是单个字段
                value = actual[key]
                return {key: value}
        # 判断响应结果数据类型:如果响应是列表类型且正则表达式不为空
        elif isinstance(actual, list) and self.read.get_case_regular(
                beforecaseid_case_row) != None:
            pattern = self.read.get_case_regular(beforecaseid_case_row)
            # 使用正则表达式匹配XMl格式响应
            value = re.findall(pattern, beforecaseid_case_actual.text)[0]
            # 获取依赖字段
            key = self.read.get_case_dependent(beforecaseid_case_row)
            return {key: value}
        # 判断响应结果数据类型:如果响应是字符串类型且正则表达式不为空
        elif isinstance(actual, str) and self.read.get_case_regular(
                beforecaseid_case_row) != None:
            # 使用正则表达式匹配XML格式响应
            pattern = self.read.get_case_regular(beforecaseid_case_row)
            value = re.findall(pattern, actual)[0]
            # 获取依赖字段
            key = self.read.get_case_dependent(beforecaseid_case_row)
            return {key: value}

    # 更新请求参数
    def get_updata_case_params_value(self, row):
        # 获取前置用例提取的结果
        if self.read.get_case_beforecaseid(row):
            dict1 = self.get_denpendent_key_value(row)
            dict2 = self.read.get_case_params_value(row)
            dict2.update(dict1)
        else:
            dict2 = self.read.get_case_params_value(row)
        return dict2


if __name__ == "__main__":
    request = RequestMethod()
    for row in range(2, 189):
        if_execute = request.read.get_case_execute(row)
        # print(RequestMethod().get_updata_case_URL(row))
        # print(RequestMethod().get_updata_case_params_value(row))
        if if_execute == 1:
            method = request.read.get_case_method(row)
            params = request.get_updata_case_params_value(row)
            url = request.get_updata_case_URL(row)
            header = request.get_updatacontenttype_case_header(row)
            actual = request.get_actual_result(method, url, params, header)
            try:
                print(actual.json())
            except:
                print(actual.text)